home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i002: RFC931 TCP Authentication server, Part02/02
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 18bc6a4c 9c051008 1e57a113 534ecf48
-
- Submitted-by: Dan Bernstein <brnstnd@acf10.nyu.edu>
- Posting-number: Volume 22, Issue 2
- Archive-name: auth2.1/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 2)."
- # Contents: attachport.c authtcp.c rfc931
- # Wrapped by rsalz@litchi.bbn.com on Mon Apr 30 15:53:40 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'attachport.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'attachport.c'\"
- else
- echo shar: Extracting \"'attachport.c'\" \(20921 characters\)
- sed "s/^X//" >'attachport.c' <<'END_OF_FILE'
- X/*
- Xattachport.c: attach a server program to a TCP port
- X*/
- X
- X/* WARNING! WARNING! WARNING! */
- X/* For the authentication to work, attachport must run setuid auth! */
- X/* All setuid programs are dangerous! Check them carefully! */
- X
- Xstatic char attachportauthor[] =
- X"attachport was written by Daniel J. Bernstein.\n\
- XInternet address: brnstnd@acf10.nyu.edu.\n";
- X
- Xstatic char attachportversion[] =
- X"attachport version 4.1, April 18, 1990.\n\
- XCopyright (c) 1990, Daniel J. Bernstein.\n\
- XAll rights reserved.\n";
- X
- Xstatic char attachportcopyright[] =
- X"attachport version 4.1, April 18, 1990.\n\
- XCopyright (c) 1990, Daniel J. Bernstein.\n\
- XAll rights reserved.\n\
- X\n\
- XUntil January 1, 1995, you are granted the following rights: A. To make\n\
- Xcopies of this work in original form, so long as (1) the copies are exact\n\
- Xand complete; (2) the copies include the copyright notice, this paragraph,\n\
- Xand the disclaimer of warranty in their entirety. B. To distribute this\n\
- Xwork, or copies made under the provisions above, so long as (1) this is\n\
- Xthe original work and not a derivative form; (2) you do not charge a fee\n\
- Xfor copying or for distribution; (3) you ensure that the distributed form\n\
- Xincludes the copyright notice, this paragraph, and the disclaimer of\n\
- Xwarranty in their entirety. These rights are temporary and revocable upon\n\
- Xwritten, oral, or other notice by Daniel J. Bernstein. These rights are\n\
- Xautomatically revoked on January 1, 1995. This copyright notice shall be\n\
- Xgoverned by the laws of the state of New York.\n\
- X\n\
- XIf you have questions about attachport or about this copyright notice,\n\
- Xor if you would like additional rights beyond those granted above,\n\
- Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- Xstatic char attachportwarranty[] =
- X"To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
- Xall warranties, explicit or implied, including but not limited to the\n\
- Ximplied warranties of merchantability and fitness for a particular purpose.\n\
- XDaniel J. Bernstein is not and shall not be liable for any damages,\n\
- Xincidental or consequential, arising from the use of this program, even\n\
- Xif you inform him of the possibility of such damages. This disclaimer\n\
- Xshall be governed by the laws of the state of New York.\n\
- X\n\
- XIn other words, use this program at your own risk.\n\
- X\n\
- XIf you have questions about attachport or about this disclaimer of warranty,\n\
- Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- Xstatic char attachportusage[] =
- X"Usage: attachport [ -01vrRxXACHUVW ] [ -pport ] program [ arg ... ]\n\
- XHelp: attachport -H\n";
- X
- Xstatic char attachporthelp[] =
- X"attachport attaches a server program to a TCP port.\n\
- X\n\
- Xattachport -A: print authorship notice\n\
- Xattachport -C: print copyright notice\n\
- Xattachport -H: print this notice\n\
- Xattachport -U: print short usage summary\n\
- Xattachport -V: print version number\n\
- Xattachport -W: print disclaimer of warranty\n\
- X\n\
- Xattachport [ -01vrRxX ] [ -pport ] program [ arg ... ]: attach program to port\n\
- X -v: verbose: proclaim success\n\
- X -1: print port number on standard output\n\
- X -0: check every ten seconds for fd 0 to have links; if none, wither away\n\
- X -x: locally authenticate connections with authd(8) (default)\n\
- X -X: do not locally authenticate\n\
- X -r: attempt to authenticate the remote side as well (default), placing\n\
- X user@host and TCP into environment variables REMOTE and PROTO\n\
- X -R: do not remotely authenticate\n\
- X -pport: attach server to a particular TCP port\n\
- X\n\
- XIf you have questions about or suggestions for attachport, please feel free\n\
- Xto contact the author, Daniel J. Bernstein, at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#ifdef BSD
- X#include <limits.h>
- X#endif
- X#include <sys/ioctl.h>
- X#include <sys/socket.h>
- X#include <sys/time.h>
- X#include <sys/wait.h>
- X#include <sys/resource.h>
- X#include <sys/stat.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <netdb.h>
- X#include <signal.h>
- X#include <sys/param.h>
- X#include <pwd.h>
- Xextern char *malloc(); /* many systems don't have malloc.h */
- Xextern int getopt();
- Xextern char *optarg; /* these should be in getopt.h! */
- Xextern int optind;
- X#include <ctype.h>
- X#include "authuser.h"
- X#include "djberr.h"
- X#include "djbatoi.h"
- X
- X#ifndef AUTHDIR
- X#define AUTHDIR "/usr/etc/auth"
- X#endif
- X
- X#ifndef MAXHOSTNAMELEN
- X#define MAXHOSTNAMELEN 128 /* stupid Suns don't define this in sys/param.h */
- X#endif
- X
- Xint numkids = 0;
- Xint flagauth = 1;
- X
- Xunsigned long myinetaddr()
- X{
- X char hn[MAXHOSTNAMELEN + 1];
- X struct hostent *he;
- X
- X if (gethostname(hn,MAXHOSTNAMELEN) == -1)
- X return((unsigned long) -1);
- X if ((he = gethostbyname(hn)) == NULL)
- X return((unsigned long) -1);
- X
- X return (*((unsigned long *) (he->h_addr)));
- X}
- X
- Xdissociatetty()
- X{
- X int fd;
- X
- X if ((fd = open("/dev/tty",O_RDWR)) == -1)
- X {
- X perrn2("%s","attachport: warning: cannot open /dev/tty");
- X }
- X else
- X {
- X if (ioctl(fd,(unsigned long) TIOCNOTTY,(char *) NULL) == -1)
- X perrn2("%s","attachport: warning: cannot dissociate /dev/tty");
- X (void) close(fd);
- X }
- X}
- X
- Xint uid;
- Xint euid;
- X
- Xint flagcheckin = 0;
- Xint alrmcounter = 0;
- X
- Xint flagdie;
- X
- Xsigterm()
- X{
- X flagdie = 1;
- X}
- X
- Xsigalrm()
- X{
- X struct stat st;
- X
- X if (flagcheckin)
- X {
- X (void) fstat(0,&st);
- X if (st.st_nlink == 0)
- X sigterm();
- X }
- X if ((++alrmcounter) % 12) /* every two minutes */
- X {
- X alrmcounter = 0;
- X (void) kill(getpid(),SIGCHLD);
- X }
- X}
- X
- Xsigchld()
- X{
- X int w;
- X char authfn[sizeof(AUTHDIR) + 30];
- X char authpfn[sizeof(AUTHDIR) + 30];
- X int authpfd;
- X int r;
- X int noweuid = geteuid();
- X
- X if (noweuid == uid) /* oopsie */
- X if (setreuid(uid,euid))
- X {
- X perrn2("%s","attachport: warning: cannot setreuid");
- X return; /* This is impossible anyway. */
- X }
- X
- X while ((w = wait3((union wait *) 0,WNOHANG,(struct rusage *) NULL)) > 0)
- X {
- X numkids--;
- X if (flagauth)
- X {
- X (void) sprintf(authpfn,"%s/tcp/ps.%d.%d",AUTHDIR,getpid(),w);
- X if ((authpfd = open(authpfn,O_RDONLY,0600)) == -1)
- X {
- X perrn2("attachport: warning: cannot unlink authentication entry %s",authpfn);
- X continue;
- X }
- X r = read(authpfd,authfn,sizeof(authfn));
- X (void) close(authpfd);
- X if ((r <= 0) || (strncmp(authfn,AUTHDIR,strlen(AUTHDIR))))
- X { /* Make sure the worst damage we can do is confined to AUTHDIR. */
- X perrn2("attachport: warning: cannot unlink authentication entry %s",authpfn);
- X continue;
- X }
- X authfn[r] = '\0';
- X if (unlink(authfn) == -1) /* had better succeed! */
- X {
- X perrn2("attachport: warning: cannot unlink authentication entry %s",authfn);
- X continue;
- X }
- X if (unlink(authpfn) == -1) /* had better succeed! */
- X {
- X perrn2("attachport: warning: cannot unlink authentication entry %s",authpfn);
- X }
- X }
- X }
- X
- X if (noweuid == uid) /* daisie */
- X if (setreuid(euid,uid))
- X {
- X perrn2("%s","attachport: warning: cannot setreuid");
- X return;
- X }
- X}
- X
- Xextern char **environ;
- X
- Xmain(argc,argv,envp)
- Xint argc;
- Xchar *argv[];
- Xchar *envp[];
- X{
- X int opt;
- X int flagverbose = 0;
- X int flagminiverb = 0;
- X int flagremote = 2;
- X char *strlocalport = "0";
- X unsigned short localport;
- X char **program = NULL;
- X struct sockaddr_in sa;
- X int s;
- X int t;
- X unsigned long in;
- X int dummy;
- X struct passwd *pw;
- X int f;
- X int authfd;
- X int authpfd;
- X char authfn[sizeof(AUTHDIR) + 30];
- X char authpfn[sizeof(AUTHDIR) + 30];
- X char lockfn[sizeof(AUTHDIR) + 30];
- X int lockfd;
- X char lockbuf[32]; /* 5 pid, 1 :, 10 I, 1 ., 5 R, 1 \n, 8 U, 1\0 */
- X /* we use just 5 pid, 1 -, 8 U, 1\0 */
- X int lockbuflen;
- X char foobuf[32];
- X struct itimerval it;
- X fd_set ready;
- X struct servent *se;
- X struct in_addr inet; /* dummy for inet_ntoa */
- X int flagsigintign;
- X int flagsigquitign;
- X int flagsigtstpign;
- X int flagsighupign;
- X int flagsigxcpuign;
- X int flagsigxfszign;
- X int flagsigvtalrmign;
- X int flagsigprofign;
- X int flagsigchldign;
- X int flagsigalrmign;
- X int flagsigtermign;
- X
- X /* ALERT! ALERT! ALERT! We're probably running setuid auth! */
- X /* Note that accounting is by real uid, not effective uid. */
- X /* The system should be careful about setuid core dumps 'n' such. */
- X
- X uid = getuid();
- X euid = geteuid();
- X
- X /* The following are necessary to be absolutely sure of removing the
- X authentication entry. It's a flaw of the signal handling system that
- X every new extension could turn a secure program like this into an
- X (ever so slightly) insecure one. */
- X flagsigintign = (signal(SIGINT,SIG_IGN) == SIG_IGN);
- X flagsigquitign = (signal(SIGQUIT,SIG_IGN) == SIG_IGN);
- X flagsigtstpign = (signal(SIGTSTP,SIG_IGN) == SIG_IGN);
- X flagsighupign = (signal(SIGHUP,SIG_IGN) == SIG_IGN);
- X flagsigxcpuign = (signal(SIGXCPU,SIG_IGN) == SIG_IGN);
- X flagsigxfszign = (signal(SIGXFSZ,SIG_IGN) == SIG_IGN);
- X flagsigvtalrmign = (signal(SIGVTALRM,SIG_IGN) == SIG_IGN);
- X flagsigprofign = (signal(SIGPROF,SIG_IGN) == SIG_IGN);
- X flagsigchldign = (signal(SIGCHLD,SIG_IGN) == SIG_IGN);
- X flagsigalrmign = (signal(SIGALRM,SIG_IGN) == SIG_IGN);
- X flagsigtermign = (signal(SIGTERM,SIG_IGN) == SIG_IGN);
- X /* At least we can depend on SIG_IGN and SIG_DFL being the only
- X possible handlers passed through an exec. Programmers should note
- X the above trick to avoid having to worry about the signal() type. */
- X
- X while ((opt = getopt(argc,argv,"01vrRxXp:ACHUVW")) != EOF)
- X switch(opt)
- X {
- X case 'v': flagverbose = 1; break;
- X case '1': flagminiverb = 1; break;
- X case '0': flagcheckin = 1; break;
- X case 'r': flagremote = 1; break;
- X case 'R': flagremote = 0; break;
- X case 'x': flagauth = 1; break;
- X case 'X': flagauth = 0; break;
- X case 'p': strlocalport = optarg; break;
- X case 'A': (void) err(attachportauthor);(void)setreuid(uid,uid); exit(1);
- X case 'C': (void) err(attachportcopyright);(void)setreuid(uid,uid); exit(1);
- X case 'H': (void) err(attachporthelp);(void)setreuid(uid,uid); exit(1);
- X case 'U': (void) err(attachportusage);(void)setreuid(uid,uid); exit(1);
- X case 'V': (void) err(attachportversion);(void)setreuid(uid,uid); exit(1);
- X case 'W': (void) err(attachportwarranty);(void)setreuid(uid,uid); exit(1);
- X case '?': (void) err(attachportusage);(void)setreuid(uid,uid); exit(1);
- X }
- X argv += optind; argc -= optind;
- X program = argv;
- X
- X if ((program == NULL) || (*program == NULL))
- X {
- X (void) err(attachportusage);
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X in = myinetaddr();
- X if (in == (unsigned long) -1)
- X {
- X (void) errn("attachport: fatal: can't find my own Internet number?!");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X t = strlen(strlocalport) - 1;
- X if (isascii(strlocalport[t]) && isdigit(strlocalport[t]))
- X localport = atoi(strlocalport); /* so who cares if it's zero? */
- X else
- X if ((se = getservbyname(strlocalport,"tcp")) == NULL)
- X localport = 0;
- X else
- X localport = ntohs(se->s_port); /* inconsistency alert! */
- X /* se->s_port is int! */
- X
- X if (flagauth)
- X if ((pw = getpwuid(uid)) == NULL)
- X {
- X (void) errn("attachport: fatal: cannot authenticate: who are you?");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X /* We now switch to the real user id, though preserving euid for auth. */
- X
- X if (setreuid(euid,uid))
- X {
- X perrn2("%s","attachport: fatal: cannot setreuid");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) /* no security problem */
- X {
- X perrn2("%s","attachport: fatal: cannot create socket");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X sa.sin_family = AF_INET;
- X sa.sin_port = htons(localport);
- X sa.sin_addr.s_addr = INADDR_ANY;
- X
- X if (bind(s,&sa,sizeof(sa)) == -1)
- X {
- X perrn2("%s","attachport: fatal: cannot bind");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X if (listen(s,5) == -1) /* 5 should be an option! */
- X {
- X perrn2("%s","attachport: fatal: cannot listen");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X dissociatetty();
- X
- X (void) signal(SIGTERM,sigterm); /* for killaport */
- X (void) signal(SIGALRM,sigalrm); /* used to be just if flagcheckin */
- X it.it_value.tv_sec = 10; it.it_value.tv_usec = 0; /* every ten seconds */
- X it.it_interval.tv_sec = 10; it.it_interval.tv_usec = 0;
- X (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
- X
- X /* we still have uids switched */
- X if (setreuid(uid,euid))
- X {
- X perrn2("%s","attachport: fatal: cannot setreuid");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X /* Now we're back to setuid auth... */
- X
- X dummy = sizeof(sa);
- X if (getsockname(s,&sa,&dummy) == -1)
- X {
- X perrn2("%s","attachport: fatal: cannot get socket name");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X if (flagremote == 2)
- X flagremote = (ntohs(sa.sin_port) != 113);
- X if (flagverbose)
- X (void) errn2("attachport: attached to port %d",ntohs(sa.sin_port));
- X if (flagminiverb)
- X {
- X (void) printf("%d\n",ntohs(sa.sin_port));
- X (void) fflush(stdout);
- X }
- X if (flagauth)
- X {
- X (void) sprintf(lockfn,"%s/tcp/lock.%u",AUTHDIR,
- X (unsigned int) ntohs(sa.sin_port));
- X if (((lockfd = open(lockfn,O_WRONLY | O_CREAT | O_EXCL,0600)) == -1)
- X &&(((lockfd = open(lockfn,O_RDONLY)) == -1)
- X ||(flock(lockfd,LOCK_EX) == -1)
- X ||(read(lockfd,lockbuf,31) <= 0)
- X ||((lockbuf[0] != '!')
- X &&((atoi(lockbuf) <= 0)
- X ||(kill(atoi(lockbuf),0) == 0))) /* okay, screw the last process */
- X ||(close(lockfd) == -1) /* impossible */
- X ||((lockfd = open(lockfn,O_WRONLY | O_CREAT | O_TRUNC,0600)) == -1)))
- X { /* yikes, that was incomprehensible */
- X errn2("attachport: fatal: local port %u locked",
- X (unsigned int) ntohs(sa.sin_port));
- X (void) setreuid(uid,uid); exit(1);
- X }
- X (void) flock(lockfd,LOCK_EX);
- X (void) sprintf(lockbuf,"%d-%s",getpid(),pw->pw_name);
- X lockbuflen = strlen(lockbuf);
- X (void) sprintf(foobuf,"!%s%d",pw->pw_name,getpid());
- X (void) write(lockfd,lockbuf,lockbuflen);
- X (void) flock(lockfd,LOCK_UN);
- X }
- X
- X /* We must remain setuid auth as long as there are live authentication */
- X /* entries. Otherwise the user could kill us and, if lucky enough, */
- X /* misauthenticate future connections. It isn't so important to worry */
- X /* about the lock file: that can only lead to a denial of service, and */
- X /* it would take a huge amount of effort to guarantee that denial. */
- X /* Anyway, we have to fork as the real uid: one system stupidity is */
- X /* that fork() uses the effective uid for MAXUPRC checks. This isn't */
- X /* a problem if there are no live authentication entries. */
- X
- X /* The solution is simple: We screw up the lock file while forking as */
- X /* the real uid, then restore it afterwards. If we're killed in the */
- X /* middle, authd will notice. This once again reduces the problem to */
- X /* denial of service, which is acceptable. (In fact, the nature of the */
- X /* messed up lock file is that it can't even cause denial of service.) */
- X /* Ha! */
- X
- X (void) signal(SIGCHLD,sigchld);
- X for (;;)
- X if (flagdie)
- X if (numkids > 0)
- X sleep(60);
- X else
- X {
- X if (flagauth)
- X (void) unlink(lockfn);
- X (void) setreuid(uid,uid); exit(0); /* ahhh, so simple */
- X }
- X else
- X {
- X FD_ZERO(&ready); /* why, oh why doesn't this pass lint? */
- X FD_SET(s,&ready);
- X while ((select(s + 1,&ready,(fd_set *) 0,(fd_set *) 0,0) < 0)
- X && !flagdie)
- X ; /* on error, ready won't be affected, so this is safe */
- X if (!flagdie) /* could be set any time, so we have to check */
- X {
- X dummy = sizeof(sa);
- X (void) flock(lockfd,LOCK_EX);
- X (void) lseek(lockfd,(off_t) 0,0);
- X (void) write(lockfd,foobuf,lockbuflen);
- X if ((t = accept(s,&sa,&dummy)) > -1)
- X if (setreuid(euid,uid))
- X {
- X perrn2("%s","attachport: warning: cannot setreuid");
- X (void) setreuid(uid,euid);
- X }
- X else if ((f = fork()) == 0)
- X {
- X if (setreuid(uid,euid))
- X {
- X perrn2("%s","attachport: fatal: cannot setreuid");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X if (flagauth)
- X {
- X (void) sprintf(authfn,"%s/tcp/%D.%d.%d",AUTHDIR,
- X sa.sin_addr.s_addr,localport,ntohs(sa.sin_port));
- X (void) sprintf(authpfn,"%s/tcp/ps.%d.%d",AUTHDIR,getppid(),getpid());
- X if ((authpfd = open(authpfn,O_WRONLY | O_CREAT | O_EXCL,0600)) == -1)
- X {
- X perrn2("%s","attachport: warning: cannot authenticate");
- X }
- X if ((authfd = open(authfn,O_WRONLY | O_CREAT | O_EXCL,0600)) == -1)
- X {
- X perrn2("%s","attachport: warning: cannot authenticate");
- X }
- X (void) write(authpfd,authfn,strlen(authfn));
- X (void) write(authfd,pw->pw_name,strlen(pw->pw_name));
- X (void) close(authpfd);
- X (void) close(authfd); /* if it fails, tough luck. */
- X }
- X
- X if (flagremote)
- X {
- X unsigned long in; /* keep confirming variables separate */
- X unsigned short local;
- X unsigned short remote;
- X char *ruser;
- X char *srem;
- X char **temp;
- X char **trem;
- X char **tproto;
- X char **envbak;
- X
- X if (auth_fd(t,&in,&local,&remote) == -1)
- X {
- X perrn2("%s","attachport: fatal: cannot confirm connection");
- X exit(1);
- X }
- X if ((ruser = auth_tcpuser(in,local,remote)) == NULL)
- X ruser = ""; /* bummer */
- X if ((srem = malloc(strlen(ruser) + 30)) == NULL)
- X {
- X perrn2("%s","attachport: fatal: cannot allocate environment");
- X exit(1);
- X }
- X inet.s_addr = in;
- X sprintf(srem,"REMOTE=%s@%s",ruser,inet_ntoa(inet));
- X for (trem = envp;*trem;trem++)
- X if (strncmp(*trem,"REMOTE=",7) == 0)
- X break;
- X for (tproto = envp;*tproto;tproto++)
- X if (strncmp(*tproto,"PROTO=",6) == 0)
- X break;
- X if (!(*trem && *tproto))
- X {
- X envbak = envp;
- X if ((environ = (char **) malloc((trem - envp + 3) * sizeof(char*)))
- X == NULL)
- X {
- X perrn2("%s","attachport: fatal: cannot allocate environment");
- X exit(1);
- X }
- X for (temp = envbak;*temp;temp++)
- X environ[temp - envbak] = *temp; /* not worth a bcopy */
- X trem = environ + ((*trem ? trem : temp++) - envbak);
- X tproto = environ + ((*tproto ? tproto : temp++) - envbak);
- X environ[temp - envbak] = NULL;
- X }
- X *trem = srem;
- X *tproto = "PROTO=TCP";
- X /* XXXXXX: Should we do confirming sanity checks here? */
- X }
- X (void) close(0); (void) dup(t);
- X (void) close(1); (void) dup(t);
- X (void) close(2); (void) dup(t);
- X for (t = getdtablesize();t > 2;t--)
- X (void) close(t);
- X
- X (void) signal(SIGINT,flagsigintign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGQUIT,flagsigquitign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGTSTP,flagsigtstpign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGHUP,flagsighupign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGXCPU,flagsigxcpuign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGXFSZ,flagsigxfszign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGVTALRM,flagsigvtalrmign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGPROF,flagsigprofign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGCHLD,flagsigchldign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGALRM,flagsigalrmign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGTERM,flagsigtermign ? SIG_IGN : SIG_DFL);
- X
- X if (setreuid(uid,uid))
- X {
- X perrn2("%s","attachport: fatal: cannot setreuid");
- X (void) setreuid(uid,uid); exit(1);
- X }
- X
- X /* Yes, Virginia, this is portable. Read execvp(3). */
- X /* Annoying that there isn't a better interface, though. */
- X (void) execvp(*program,program); /* must use environ! */
- X /* option to yell to remote end about failure? hmmm */
- X exit(1);
- X }
- X else if (f == -1)
- X {
- X /* option to yell to remote end before closing? perhaps */
- X (void) close(t); /* sigh */
- X if (setreuid(uid,euid))
- X {
- X perrn2("%s","attachport: warning: cannot setreuid");
- X (void) setreuid(uid,euid);
- X }
- X }
- X else
- X {
- X if (setreuid(uid,euid))
- X {
- X perrn2("%s","attachport: warning: cannot setreuid");
- X (void) setreuid(uid,euid);
- X }
- X numkids++;
- X (void) close(t);
- X }
- X (void) lseek(lockfd,(off_t) 0,0);
- X (void) write(lockfd,lockbuf,lockbuflen);
- X (void) flock(lockfd,LOCK_UN);
- X }
- X }
- X /*NOTREACHED*/
- X}
- END_OF_FILE
- if test 20921 -ne `wc -c <'attachport.c'`; then
- echo shar: \"'attachport.c'\" unpacked with wrong size!
- fi
- # end of 'attachport.c'
- fi
- if test -f 'authtcp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'authtcp.c'\"
- else
- echo shar: Extracting \"'authtcp.c'\" \(19108 characters\)
- sed "s/^X//" >'authtcp.c' <<'END_OF_FILE'
- X/*
- Xauthtcp.c: Create a locally authenticated TCP connection.
- X*/
- X
- X/* WARNING! WARNING! WARNING! */
- X/* For the authentication to work, authtcp must run setuid auth! */
- X/* All setuid programs are dangerous! Check them carefully! */
- X
- Xstatic char authtcpauthor[] =
- X"authtcp was written by Daniel J. Bernstein.\n\
- XInternet address: brnstnd@acf10.nyu.edu.\n";
- X
- Xstatic char authtcpversion[] =
- X"authtcp version 2.1, April 18, 1990.\n\
- XCopyright (c) 1990, Daniel J. Bernstein.\n\
- XAll rights reserved.\n";
- X
- Xstatic char authtcpcopyright[] =
- X"authtcp version 2.1, April 18, 1990.\n\
- XCopyright (c) 1990, Daniel J. Bernstein.\n\
- XAll rights reserved.\n\
- X\n\
- XUntil January 1, 1995, you are granted the following rights: A. To make\n\
- Xcopies of this work in original form, so long as (1) the copies are exact\n\
- Xand complete; (2) the copies include the copyright notice, this paragraph,\n\
- Xand the disclaimer of warranty in their entirety. B. To distribute this\n\
- Xwork, or copies made under the provisions above, so long as (1) this is\n\
- Xthe original work and not a derivative form; (2) you do not charge a fee\n\
- Xfor copying or for distribution; (3) you ensure that the distributed form\n\
- Xincludes the copyright notice, this paragraph, and the disclaimer of\n\
- Xwarranty in their entirety. These rights are temporary and revocable upon\n\
- Xwritten, oral, or other notice by Daniel J. Bernstein. These rights are\n\
- Xautomatically revoked on January 1, 1995. This copyright notice shall be\n\
- Xgoverned by the laws of the state of New York.\n\
- X\n\
- XIf you have questions about authtcp or about this copyright notice,\n\
- Xor if you would like additional rights beyond those granted above,\n\
- Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- Xstatic char authtcpwarranty[] =
- X"To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
- Xall warranties, explicit or implied, including but not limited to the\n\
- Ximplied warranties of merchantability and fitness for a particular purpose.\n\
- XDaniel J. Bernstein is not and shall not be liable for any damages,\n\
- Xincidental or consequential, arising from the use of this program, even\n\
- Xif you inform him of the possibility of such damages. This disclaimer\n\
- Xshall be governed by the laws of the state of New York.\n\
- X\n\
- XIn other words, use this program at your own risk.\n\
- X\n\
- XIf you have questions about authtcp or about this disclaimer of warranty,\n\
- Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- Xstatic char authtcpusage[] =
- X"Usage: authtcp [ -dn ] [ -pport ] [ -xXvACHUVW ] inetaddr tcpport program \n\
- XHelp: authtcp -H\n";
- X
- Xstatic char authtcphelp[] =
- X"authtcp creates a locally authenticated TCP connection to an Internet host.\n\
- X\n\
- Xauthtcp -A: print authorship notice\n\
- Xauthtcp -C: print copyright notice\n\
- Xauthtcp -H: print this notice\n\
- Xauthtcp -U: print short usage summary\n\
- Xauthtcp -V: print version number\n\
- Xauthtcp -W: print disclaimer of warranty\n\
- X\n\
- Xauthtcp [ -dn ] [ -pport ] [ -vxXrR ] inetaddr tcpport program:\n\
- X connect to tcpport at inetaddr and run program\n\
- X -dn: pass the connection to the program in file descriptor n (default 6)\n\
- X -pport: attempt to use a particular local port\n\
- X -v: verbose: proclaim success; report unusual program termination\n\
- X -x: authenticate by telling authd(8) about the connection (default)\n\
- X -X: do not locally authenticate\n\
- X -r: attempt to authenticate the remote side as well (default), placing\n\
- X user@host and TCP into environment variables REMOTE and PROTO\n\
- X -R: do not remotely authenticate\n\
- X\n\
- XIf you have questions about or suggestions for authtcp, please feel free\n\
- Xto contact the author, Daniel J. Bernstein, at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <netdb.h>
- X#include <errno.h>
- Xextern int errno;
- Xextern char *malloc(); /* many systems don't have malloc.h */
- X#include <pwd.h>
- X#include <sys/file.h>
- X#ifdef BSD
- X#include <limits.h>
- X#endif
- X#include <sys/wait.h>
- X#include <sys/time.h>
- X#include <sys/resource.h>
- X#include <signal.h>
- X#include <ctype.h>
- Xextern int getopt();
- Xextern char *optarg; /* these should be in getopt.h! */
- Xextern int optind;
- X#include "authuser.h"
- X#include "djberr.h"
- X#include "djbatoi.h"
- X
- X#ifndef AUTHDIR
- X#define AUTHDIR "/usr/etc/auth"
- X#endif
- X
- X#ifndef MAXHOSTNAMELEN
- X#define MAXHOSTNAMELEN 128 /* stupid Suns don't define this in sys/param.h */
- X#endif
- X
- Xint flagcont = 0;
- X
- Xsigcont()
- X{
- X flagcont = 1;
- X}
- X
- Xint flagauth = 1;
- Xint flagremote = 1;
- Xint filedesc = 6;
- Xunsigned short localport = 0;
- X
- Xchar *strinetaddr = NULL;
- Xchar *strtcpport = NULL;
- Xchar **program = NULL;
- X
- Xmain(argc,argv,envp)
- Xint argc;
- Xchar *argv[];
- Xchar *envp[];
- X{
- X extern char **environ;
- X int opt;
- X struct sockaddr_in sa;
- X unsigned long in;
- X unsigned short remoteport;
- X int s;
- X int t;
- X int uid;
- X int euid;
- X int dummy;
- X char authfn[sizeof(AUTHDIR) + 30];
- X int authfd;
- X char lockfn[sizeof(AUTHDIR) + 30];
- X int lockfd;
- X char lockbuf[32]; /* 5 pid, 1 :, 10 I, 1 ., 5 R, 1 \n, 8 U, 1\0 */
- X struct passwd *pw;
- X char strfd[20];
- X int flagverbose = 0;
- X struct hostent *he;
- X struct servent *se;
- X union wait status;
- X int f;
- X struct in_addr inet; /* dummy for inet_ntoa() */
- X int flagsigintign;
- X int flagsigquitign;
- X int flagsigtstpign;
- X int flagsighupign;
- X int flagsigalrmign;
- X int flagsigxcpuign;
- X int flagsigxfszign;
- X int flagsigvtalrmign;
- X int flagsigprofign;
- X
- X /* ALERT! ALERT! ALERT! We're probably running setuid auth! */
- X /* Note that accounting is by real uid, not effective uid. */
- X /* The system should be careful about setuid core dumps 'n' such. */
- X
- X uid = getuid();
- X euid = geteuid();
- X
- X /* The following are necessary to be absolutely sure of removing the
- X authentication entry. It's a flaw of the signal handling system that
- X every new extension could turn a secure program like this into an
- X (ever so slightly) insecure one. */
- X flagsigintign = (signal(SIGINT,SIG_IGN) == SIG_IGN);
- X flagsigquitign = (signal(SIGQUIT,SIG_IGN) == SIG_IGN);
- X flagsigtstpign = (signal(SIGTSTP,SIG_IGN) == SIG_IGN);
- X flagsighupign = (signal(SIGHUP,SIG_IGN) == SIG_IGN);
- X flagsigalrmign = (signal(SIGALRM,SIG_IGN) == SIG_IGN);
- X flagsigxcpuign = (signal(SIGXCPU,SIG_IGN) == SIG_IGN);
- X flagsigxfszign = (signal(SIGXFSZ,SIG_IGN) == SIG_IGN);
- X flagsigvtalrmign = (signal(SIGVTALRM,SIG_IGN) == SIG_IGN);
- X flagsigprofign = (signal(SIGPROF,SIG_IGN) == SIG_IGN);
- X /* At least we can depend on SIG_IGN and SIG_DFL being the only
- X possible handlers passed through an exec. Programmers should note
- X the above trick to avoid having to worry about the signal() type. */
- X
- X while ((opt = getopt(argc,argv,"rRxXd:p:vACHUVW")) != EOF)
- X switch(opt)
- X {
- X case 'r': flagremote = 1; break;
- X case 'R': flagremote = 0; break;
- X case 'x': flagauth = 1; break;
- X case 'X': flagauth = 0; break;
- X case 'd': filedesc = atoi(optarg); break;
- X case 'p': localport = atoi(optarg); break;
- X case 'v': flagverbose = 1; break;
- X case 'A': (void) err(authtcpauthor); (void) setreuid(uid,uid); exit(1);
- X case 'C': (void) err(authtcpcopyright); (void) setreuid(uid,uid); exit(1);
- X case 'H': (void) err(authtcphelp); (void) setreuid(uid,uid); exit(1);
- X case 'U': (void) err(authtcpusage); (void) setreuid(uid,uid); exit(1);
- X case 'V': (void) err(authtcpversion); (void) setreuid(uid,uid); exit(1);
- X case 'W': (void) err(authtcpwarranty); (void) setreuid(uid,uid); exit(1);
- X case '?': (void) err(authtcpusage); (void) setreuid(uid,uid); exit(1);
- X }
- X argv += optind, argc -= optind;
- X while (*argv)
- X {
- X if (strinetaddr == NULL)
- X strinetaddr = *argv;
- X else if (strtcpport == NULL)
- X strtcpport = *argv;
- X else
- X {
- X program = argv;
- X break;
- X }
- X argv++;
- X }
- X
- X if ((program == NULL) || (*program == NULL))
- X {
- X err(authtcpusage); (void) setreuid(uid,uid); exit(1);
- X /* what else can you say? */
- X }
- X
- X t = strlen(strinetaddr) - 1;
- X if (isascii(strinetaddr[t]) && isdigit(strinetaddr[t]))
- X in = inet_addr(strinetaddr);
- X else
- X if ((he = gethostbyname(strinetaddr)) == NULL)
- X in = (unsigned long) -1;
- X else
- X in = *((unsigned long *) (he->h_addr));
- X
- X if (in == (unsigned long) -1)
- X {
- X errn2("authtcp: fatal: do not understand inetaddr %s",strinetaddr);
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X
- X t = strlen(strtcpport) - 1;
- X if (isascii(strtcpport[t]) && isdigit(strtcpport[t]))
- X remoteport = atoi(strtcpport); /* so who cares if it's zero? */
- X else
- X if ((se = getservbyname(strtcpport,"tcp")) == NULL)
- X remoteport = 0;
- X else
- X remoteport = ntohs(se->s_port); /* inconsistency alert! */
- X /* se->s_port is int! */
- X
- X /* We will depend on the type of localport and remoteport, namely */
- X /* unsigned short, to keep them between 0 and 65535. */
- X
- X /* The parent program must remain active and setuid auth, to wait for */
- X /* the child to finish and to remove its authentication entry. But the */
- X /* TCP connection must be made as the user---don't want fake rlogins! */
- X
- X /* We now switch to the real user ID. */
- X
- X if (setreuid(euid,uid))
- X {
- X perrn2("%s","authtcp: fatal: cannot setreuid");
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X
- X if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) /* no security problem */
- X {
- X perrn2("%s","authtcp: fatal: cannot create socket");
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X
- X /* The bind() below used to be if (localport) only. However, connect() */
- X /* can take arbitrarily long, there's no solution like select-accept, */
- X /* and authd should not have to wait to get its information. So we have */
- X /* to find our local port now. This is documented to work in PS1:8-31. */
- X
- X sa.sin_family = AF_INET;
- X sa.sin_port = htons(localport); /* ever seen a client do this before? */
- X sa.sin_addr.s_addr = INADDR_ANY; /* or this? */
- X
- X if (bind(s,&sa,sizeof(sa)) == -1)
- X if (localport)
- X {
- X perrn2("authtcp: fatal: cannot bind local port %u",
- X (unsigned int) localport);
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X else
- X {
- X perrn2("%s","authtcp: fatal: cannot bind local port");
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X
- X /* We now switch back to auth... */
- X if (setreuid(uid,euid))
- X {
- X perrn2("%s","authtcp: fatal: cannot setreuid");
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X
- X if (flagauth)
- X {
- X dummy = sizeof(sa);
- X if ((pw = getpwuid(uid)) == NULL)
- X {
- X errn("authtcp: fatal: cannot authenticate: who are you?");
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X if (getsockname(s,&sa,&dummy) == -1)
- X {
- X perrn2("%s","authtcp: fatal: cannot get socket name");
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X (void) sprintf(authfn,"%s/tcp/%D.%u.%u",AUTHDIR,in,
- X (unsigned int) ntohs(sa.sin_port),(unsigned int) remoteport);
- X (void) sprintf(lockfn,"%s/tcp/lock.%u",AUTHDIR,
- X (unsigned int) ntohs(sa.sin_port));
- X if (((lockfd = open(lockfn,O_WRONLY | O_CREAT | O_EXCL,0600)) == -1)
- X &&(((lockfd = open(lockfn,O_RDONLY)) == -1)
- X ||(flock(lockfd,LOCK_EX) == -1)
- X ||(read(lockfd,lockbuf,31) <= 0)
- X ||((lockbuf[0] != '!')
- X &&((atoi(lockbuf) <= 0)
- X ||(kill(atoi(lockbuf),0) == 0))) /* okay, screw the last process */
- X ||(close(lockfd) == -1) /* impossible */
- X ||((lockfd = open(lockfn,O_WRONLY | O_CREAT | O_TRUNC,0600)) == -1)))
- X { /* yikes, that was incomprehensible */
- X errn2("authtcp: fatal: local port %u locked",
- X (unsigned int) ntohs(sa.sin_port));
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X (void) flock(lockfd,LOCK_EX);
- X (void) sprintf(lockbuf,"%d:%D.%u\n%s",getpid(),in,(unsigned int) remoteport,
- X pw->pw_name);
- X (void) write(lockfd,lockbuf,strlen(lockbuf));
- X (void) flock(lockfd,LOCK_UN);
- X }
- X /* It isn't a disaster if the user kills us now; it's just a possible */
- X /* denial of service for later auths on this port. The amount of effort */
- X /* necessary to guarantee that denial is huge. */
- X
- X /* We now switch back to real... */
- X if (setreuid(euid,uid))
- X {
- X perrn2("%s","authtcp: fatal: cannot setreuid");
- X (void) setreuid(uid,euid);
- X if (flagauth)
- X (void) unlink(lockfn);
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X
- X sa.sin_family = AF_INET;
- X sa.sin_port = htons(remoteport);
- X sa.sin_addr.s_addr = in;
- X
- X if (connect(s,&sa,sizeof(sa)) == -1)
- X {
- X perrn2("authtcp: fatal: cannot connect to %s",strinetaddr);
- X (void) setreuid(uid,euid);
- X if (flagauth)
- X (void) unlink(lockfn);
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X
- X if (flagverbose)
- X {
- X inet.s_addr = in;
- X fprintf(stderr,"authtcp: connected to %s port %u\n",
- X inet_ntoa(inet),(unsigned int) remoteport);
- X }
- X
- X /* We now have the uids switched, the connection open in socket s. */
- X
- X /* We're about to write the authentication entry. We must remove it */
- X /* before coming back to the real uid and/or exiting. On the other */
- X /* hand, we must fork as the real uid: one system stupidity is that */
- X /* fork() uses the effective uid for MAXUPRC checks. Hence we fork */
- X /* as the real (i.e. switched) uid, before authentication. In fact, */
- X /* we delay authentication until it's convenient in the parent; the */
- X /* child program could run before the authentication file exists. */
- X /* This is not a race condition, for reasons explained in dir.doc. */
- X
- X if ((f = fork()) == 0) /* child */
- X {
- X if (setreuid(uid,uid))
- X {
- X perrn2("%s","authtcp: fatal: cannot setreuid");
- X exit(1);
- X }
- X if (filedesc)
- X {
- X if (dup2(s,filedesc) == -1)
- X {
- X perrn2("%s","authtcp: fatal: cannot use file descriptor");
- X exit(1);
- X }
- X }
- X else
- X {
- X (void) sprintf(strfd,"%d",s);
- X while (*(++argv))
- X if ((**argv == '=') && (*(*argv + 1) == '\0'))
- X {
- X *argv = strfd;
- X break;
- X }
- X /* don't need to complain about failure here */
- X }
- X
- X if (flagremote)
- X {
- X unsigned long in; /* keep confirming variables separate */
- X unsigned short local;
- X unsigned short remote;
- X char *ruser;
- X char *srem;
- X char **t;
- X char **trem;
- X char **tproto;
- X char **envbak;
- X
- X if (auth_fd(s,&in,&local,&remote) == -1)
- X {
- X perrn2("%s","authtcp: fatal: cannot confirm connection");
- X exit(1);
- X }
- X if ((ruser = auth_tcpuser(in,local,remote)) == NULL)
- X ruser = ""; /* bummer */
- X if ((srem = malloc(strlen(ruser) + 30)) == NULL)
- X {
- X perrn2("%s","authtcp: fatal: cannot allocate environment");
- X exit(1);
- X }
- X inet.s_addr = in;
- X sprintf(srem,"REMOTE=%s@%s",ruser,inet_ntoa(inet));
- X for (trem = envp;*trem;trem++)
- X if (strncmp(*trem,"REMOTE=",7) == 0)
- X break;
- X for (tproto = envp;*tproto;tproto++)
- X if (strncmp(*tproto,"PROTO=",6) == 0)
- X break;
- X if (!(*trem && *tproto))
- X {
- X envbak = envp;
- X if ((environ = (char **) malloc((trem - envp + 3) * sizeof(char *)))
- X == NULL)
- X {
- X perrn2("%s","authtcp: fatal: cannot allocate environment");
- X exit(1);
- X }
- X for (t = envbak;*t;t++)
- X environ[t - envbak] = *t; /* not worth a bcopy */
- X trem = environ + ((*trem ? trem : t++) - envbak);
- X tproto = environ + ((*tproto ? tproto : t++) - envbak);
- X environ[t - envbak] = NULL;
- X }
- X *trem = srem;
- X *tproto = "PROTO=TCP";
- X /* XXXXXX: Should we do confirming sanity checks here? */
- X }
- X
- X (void) signal(SIGINT,flagsigintign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGQUIT,flagsigquitign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGTSTP,flagsigtstpign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGHUP,flagsighupign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGALRM,flagsigalrmign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGXCPU,flagsigxcpuign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGXFSZ,flagsigxfszign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGVTALRM,flagsigvtalrmign ? SIG_IGN : SIG_DFL);
- X (void) signal(SIGPROF,flagsigprofign ? SIG_IGN : SIG_DFL);
- X
- X /* Yes, Virginia, this is portable. Read execvp(3). */
- X /* Annoying that there isn't a better interface, though. */
- X (void) execvp(*program,program); /* must use environ! */
- X perrn2("authtcp: fatal: cannot execute %s",*program);
- X exit(1);
- X }
- X /* no need to test for failing fork */
- X
- X if (setreuid(uid,euid))
- X {
- X perrn2("%s","authtcp: fatal: cannot setreuid");
- X (void) setreuid(uid,euid);
- X if (flagauth)
- X (void) unlink(lockfn);
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X /* Now we're back to setuid auth in the parent, as we will remain. */
- X
- X if (flagauth)
- X {
- X /* authfn and pw are put together up above */
- X if ((authfd = open(authfn,O_WRONLY | O_CREAT | O_EXCL,0600)) == -1)
- X {
- X perrn2("%s","authtcp: fatal: cannot authenticate");
- X (void) setreuid(uid,euid);
- X if (flagauth)
- X (void) unlink(lockfn);
- X (void) setreuid(uid,uid);
- X exit(1);
- X }
- X (void) write(authfd,pw->pw_name,strlen(pw->pw_name));
- X (void) close(authfd); /* if it fails, tough luck. */
- X }
- X
- X (void) signal(SIGCONT,sigcont);
- X
- X /* Unless the user is auth we won't receive any signals. So the */
- X /* following handlers are mainly a convenience on machines where */
- X /* authtcp is not installed by the sysadmin. */
- X (void) signal(SIGTERM,SIG_IGN); /* kill child, not us! */
- X (void) signal(SIGTTOU,SIG_DFL); /* for stopping */
- X (void) signal(SIGTTIN,SIG_DFL); /* for stopping */
- X
- X /* We're going to leave the socket open, to completely close a possible */
- X /* security hole. The application must not depend upon the connection */
- X /* disappearing when it's closed. */
- X
- X for (t = getdtablesize();t >= 0;t--)
- X if ((s != t) && (t != 2)) /* have to leave stderr open! */
- X (void) close(t); /* might as well do a bit of dissociation */
- X
- X while (wait3(&status,WUNTRACED,(struct rusage *) NULL) >= 0)
- X {
- X if (status.w_stopval == WSTOPPED) /* if child stops, we stop */
- X {
- X flagcont = 0;
- X (void) signal(SIGTSTP,SIG_DFL); /* for stopping */
- X switch(status.w_stopsig)
- X { /* this just looks good */
- X case SIGSTOP: (void) kill(getpid(),SIGSTOP); break;
- X case SIGTSTP: (void) kill(getpid(),SIGTSTP); break;
- X case SIGTTOU: (void) kill(getpid(),SIGTTOU); break;
- X case SIGTTIN: (void) kill(getpid(),SIGTTIN); break;
- X default: (void) kill(getpid(),SIGSTOP); break;
- X }
- X while (flagcont == 0)
- X ; /* rack up CPU time waiting for the CONT---is there a better way? */
- X (void) signal(SIGTSTP,SIG_IGN);
- X (void) kill(f,SIGCONT); /* when we start, child starts */
- X continue;
- X }
- X if (flagverbose)
- X if (WIFSIGNALED(status))
- X if (status.w_coredump)
- X {
- X errn2("authtcp: fatal: killed by signal %d (core dumped)",
- X status.w_termsig);
- X }
- X else
- X {
- X errn2("authtcp: fatal: killed by signal %d",status.w_termsig);
- X }
- X break;
- X }
- X
- X if (flagauth)
- X {
- X if (unlink(authfn) == -1) /* had better succeed! */
- X {
- X perrn2("authtcp: fatal: cannot unlink authentication entry %s",authfn);
- X exit(1);
- X }
- X (void) unlink(lockfn);
- X }
- X
- X exit(WIFEXITED(status) ? ((int) status.w_retcode) : 1);
- X}
- END_OF_FILE
- if test 19108 -ne `wc -c <'authtcp.c'`; then
- echo shar: \"'authtcp.c'\" unpacked with wrong size!
- fi
- # end of 'authtcp.c'
- fi
- if test -f 'rfc931' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rfc931'\"
- else
- echo shar: Extracting \"'rfc931'\" \(9196 characters\)
- sed "s/^X//" >'rfc931' <<'END_OF_FILE'
- X
- X
- X
- X
- X
- X---------
- X
- X
- X< INC-PROJECT, AUTH-RFC-VER-2.NLS.5, >, 7-Jan-85 17:18-PST JBP
- X;;;;
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- XStJohns [Page 0]
- X
- X
- XNetwork Working Group Mike StJohns
- XRequest for Comments: 931 TPSC
- XSupersedes: RFC 912 January 1985
- X
- X Authentication Server
- X
- X
- XSTATUS OF THIS MEMO
- X
- X This RFC suggests a proposed protocol for the ARPA-Internet
- X community, and requests discussion and suggestions for improvements.
- X This is the second draft of this proposal (superseding RFC 912) and
- X incorporates a more formal description of the syntax for the request
- X and response dialog, as well as a change to specify the type of user
- X identification returned. Distribution of this memo is unlimited.
- X
- XINTRODUCTION
- X
- X The Authentication Server Protocol provides a means to determine the
- X identity of a user of a particular TCP connection. Given a TCP port
- X number pair, it returns a character string which identifies the owner
- X of that connection on the server's system. Suggested uses include
- X automatic identification and verification of a user during an FTP
- X session, additional verification of a TAC dial up user, and access
- X verification for a generalized network file server.
- X
- XOVERVIEW
- X
- X This is a connection based application on TCP. A server listens for
- X TCP connections on TCP port 113 (decimal). Once a connection is
- X established, the server reads one line of data which specifies the
- X connection of interest. If it exists, the system dependent user
- X identifier of the connection of interest is sent out the connection.
- X The service closes the connection after sending the user identifier.
- X
- XRESTRICTIONS
- X
- X Queries are permitted only for fully specified connections. The
- X local/foreign host pair used to fully specify the connection are
- X taken from the query connection. This means a user on Host A may
- X only query the server on Host B about connections between A and B.
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- XStJohns [Page 1]
- X
- X
- XRFC 931 January 1985
- XAuthentication Server
- X
- X
- XQUERY/RESPONSE FORMAT
- X
- X The server accepts simple text query requests of the form
- X
- X <local-port>, <foreign-port>
- X
- X where <local-port> is the TCP port (decimal) on the target (server)
- X system, and <foreign-port> is the TCP port (decimal) on the source
- X (user) system.
- X
- X For example:
- X
- X 23, 6191
- X
- X The response is of the form
- X
- X <local-port>, <foreign-port> : <response-type> : <additional-info>
- X
- X where <local-port>,<foreign-port> are the same pair as the query,
- X <response-type> is a keyword identifying the type of response, and
- X <additional info> is context dependent.
- X
- X For example:
- X
- X 23, 6191 : USERID : MULTICS : StJohns.DODCSC.a
- X 23, 6193 : USERID : TAC : MCSJ-MITMUL
- X 23, 6195 : ERROR : NO-USER
- X
- XRESPONSE TYPES
- X
- X A response can be one of two types:
- X
- X USERID
- X
- X In this case, <additional-info> is a string consisting of an
- X operating system name, followed by a ":", followed by user
- X identification string in a format peculiar to the operating system
- X indicated. Permitted operating system names are specified in
- X RFC-923, "Assigned Numbers" or its successors. The only other
- X names permitted are "TAC" to specify a BBN Terminal Access
- X Controller, and "OTHER" to specify any other operating system not
- X yet registered with the NIC.
- X
- X
- X
- X
- X
- X
- X
- XStJohns [Page 2]
- X
- X
- XRFC 931 January 1985
- XAuthentication Server
- X
- X
- X ERROR
- X
- X For some reason the owner of <TCP-port> could not be determined,
- X <additional-info> tells why. The following are suggested values
- X of <additional-info> and their meanings.
- X
- X INVALID-PORT
- X
- X Either the local or foreign port was improperly specified.
- X
- X NO-USER
- X
- X The connection specified by the port pair is not currently in
- X use.
- X
- X UNKNOWN-ERROR
- X
- X Can't determine connection owner; reason unknown. Other values
- X may be specified as necessary.
- X
- XCAVEATS
- X
- X Unfortunately, the trustworthiness of the various host systems that
- X might implement an authentication server will vary quite a bit. It
- X is up to the various applications that will use the server to
- X determine the amount of trust they will place in the returned
- X information. It may be appropriate in some cases restrict the use of
- X the server to within a locally controlled subnet.
- X
- XAPPLICATIONS
- X
- X 1) Automatic user authentication for FTP
- X
- X A user-FTP may send a USER command with no argument to the
- X server-FTP to request automatic authentication. The server-FTP
- X will reply with a 230 (user logged in) if it can use the
- X authentication. It will reply with a 530 (not logged in) if it
- X cannot authenticate the user. It will reply with a 500 or 501
- X (syntax or parameter problem) if it does not implement automatic
- X authentication. Please note that no change is needed to currently
- X implemented servers to handle the request for authentication; they
- X will reject it normally as a parameter problem. This is a
- X suggested implementation for experimental use only.
- X
- X 2) Verification for privileged network operations. For example,
- X having the server start or stop special purpose servers.
- X
- X
- X
- XStJohns [Page 3]
- X
- X
- XRFC 931 January 1985
- XAuthentication Server
- X
- X
- X 3) Elimination of "double login" for TAC and other TELNET users.
- X
- X This will be implemented as a TELNET option.
- X
- XFORMAL SYNTAX
- X
- X <request> ::= <port-pair> <CR> <LF>
- X
- X <port-pair> ::= <integer-number> "," <integer-number>
- X
- X <reply> ::= <reply-text> <CR> <LF>
- X
- X <reply-text> ::= <error-reply> | <auth-reply>
- X
- X <error-reply> ::= <port-pair> ":" ERROR ":" <error-type>
- X
- X <auth-reply> ::= <port-pair> ":" USERID ":" <opsys> ":" <user-id>
- X
- X <error-type> ::= INVALID-PORT | NO-USER | UNKNOWN-ERROR
- X
- X <opsys> ::= TAC | OTHER | MULTICS | UNIX ...etc.
- X (See "Assigned Numbers")
- X
- X Notes on Syntax:
- X
- X 1) White space (blanks and tab characters) between tokens is not
- X important and may be ignored.
- X
- X 2) White space, the token separator character (":"), and the port
- X pair separator character (",") must be quoted if used within a
- X token. The quote character is a back-slash, ASCII 92 (decimal)
- X ("\"). For example, a quoted colon is "\:". The back-slash must
- X also be quoted if its needed to represent itself ("\\").
- X
- XNotes on User Identification Format:
- X
- X The user identifier returned by the server should be the standard one
- X for the system. For example, the standard Multics identifier
- X consists of a PERSONID followed by a ".", followed by a PROJECTID,
- X followed by a ".", followed by an INSTANCE TAG of one character. An
- X instance tag of "a" identifies an interactive user, and instance tag
- X of "m" identifies an absentee job (batch job) user, and an instance
- X tag of "z" identifies a daemon (background) user.
- X
- X Each set of operating system users must come to a consensus as to
- X
- X
- X
- X
- XStJohns [Page 4]
- X
- X
- XRFC 931 January 1985
- XAuthentication Server
- X
- X
- X what the OFFICIAL user identification for their systems will be.
- X Until they register this information, they must use the "OTHER" tag
- X to specify their user identification.
- X
- XNotes on User Identification Translation:
- X
- X Once you have a user identifier from a remote system, you must then
- X have a way of translating it into an identifier that meaningful on
- X the local system. The following is a sketchy outline of table driven
- X scheme for doing this.
- X
- X The table consists of four columns, the first three are used to match
- X against, the fourth is the result.
- X
- X USERID Opsys Address Result
- X MCSJ-MITMUL TAC 26.*.*.* StJohns
- X * MULTICS 192.5.42.* =
- X * OTHER 10.0.0.42 anonymous
- X MSJ ITS 10.3.0.44 StJohns
- X
- X The above table is a sample one for a Multics system on MILNET at the
- X Pentagon. When an authentication is returned, the particular
- X application using the userid simply looks for the first match in the
- X table. Notice the second line. It says that any authentication
- X coming from a Multics system on Net 192.5.42 is accepted in the same
- X format.
- X
- X Obviously, various users will have to be registered to use this
- X facility, but the registration can be done at the same time the use
- X receives his login identity from the system.
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- XStJohns [Page 5]
- END_OF_FILE
- if test 9196 -ne `wc -c <'rfc931'`; then
- echo shar: \"'rfc931'\" unpacked with wrong size!
- fi
- # end of 'rfc931'
- fi
- echo shar: End of archive 2 \(of 2\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- exit 0 # Just in case...
-